package app.services.impl;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.httpclient.util.DateParseException;

import app.models.Consulta;
import app.models.Credito;
import app.models.Debito;
import app.models.Relatorio;
import app.models.enums.StatusConsulta;
import app.models.enums.TipoCaixa;
import app.models.enums.TipoConsulta;
import app.models.to.RelatorioConsulta;
import app.models.to.RelatorioFaturamento;
import app.repositories.ConsultaRepository;
import app.repositories.CreditoRepository;
import app.repositories.DebitoRepository;
import app.repositories.RelatorioRepository;
import app.services.RelatorioService;
import app.util.DateUtils;
import br.com.caelum.vraptor.ioc.Component;

@Component
public class RelatorioServiceImpl 
	extends GenericServiceImpl<Relatorio, Long> implements RelatorioService {

	private final RelatorioRepository repository;
	private final ConsultaRepository consultaRepository;
	private final DebitoRepository debitoRepository;
	private final CreditoRepository creditoRepository;
	
	public RelatorioServiceImpl(RelatorioRepository repository, ConsultaRepository consultaRepository,
			DebitoRepository debitoRepository, CreditoRepository creditoRepository) {
		this.repository = repository;
		this.consultaRepository = consultaRepository;
		this.debitoRepository = debitoRepository;
		this.creditoRepository = creditoRepository;
	}
	
	
	@Override
	public List<Consulta> findConsultasUnpaidUntilTodayByFilter(String filter) {
		return repository.findConsultasUnpaidUntilTodayByFilter(filter);
	}
	
	@Override
	public List<RelatorioConsulta> findRelatorioConsultasByFilters(Consulta consulta) throws ParseException, DateParseException {
		
		Double valorBruto = 0.0;
		Double valorLiquido = 0.0;
		
		List<RelatorioConsulta> relatorioConsultas = new ArrayList<RelatorioConsulta>();
		
		List<Consulta> consultas = consultaRepository.findConsultasByFilters(consulta);
		
		Integer qtAtrasada = 0;
		Integer qtCancelada = 0;
		Integer qtFinalizada = 0;
		Integer qtMarcada = 0;
		Integer qtPaga = 0;
		Integer qtPendente = 0;
		Integer qtRealizada = 0;
		Integer qtTotal = 0;
		
		for (Consulta c : consultas) {
			if (c.getStatus().equals(StatusConsulta.ATRASADA)) {
				qtAtrasada += 1;
			} else if (c.getStatus().equals(StatusConsulta.CANCELADA)) {
				qtCancelada += 1;
			} else if (c.getStatus().equals(StatusConsulta.FINALIZADA)) {
				qtFinalizada += 1;
			} else if (c.getStatus().equals(StatusConsulta.MARCADA)) {
				qtMarcada += 1;
			} else if (c.getStatus().equals(StatusConsulta.PAGA)) {
				qtPaga += 1;
			} else if (c.getStatus().equals(StatusConsulta.PENDENTE)) {
				qtPendente += 1;
			} else if (c.getStatus().equals(StatusConsulta.REALIZADA)) {
				qtRealizada += 1;
			}
			
			qtTotal += 1;
		}
		
		for (Consulta c : consultas) {
			RelatorioConsulta relatorioConsulta = new RelatorioConsulta();
			
			relatorioConsulta.setDataInicial(DateUtils.convertDataStrToDate(consulta.getDataInicial()));
			relatorioConsulta.setDataFinal(DateUtils.convertDataStrToDate(consulta.getDataFinal()));
			
			relatorioConsulta.setTipo(c.getTipo().toString());
			relatorioConsulta.setDataConsulta(DateUtils.convertDataStrToDate(c.getData()));
			
			if (null != c.getDataPagamento()) {
				relatorioConsulta.setDataPagamento(DateUtils.convertDataStrToDate(c.getDataPagamento()));
			}
			
			if (null != c.getEspecialidade()) {
				relatorioConsulta.setNomeEspecialidade(c.getEspecialidade().getNome());
			} else if (null != c.getSubEspecialidade()) {
				relatorioConsulta.setNomeEspecialidade(c.getSubEspecialidade().getNome());
			}
			
			relatorioConsulta.setNomeEspecialista(c.getEspecialista().getUsuario().getNome());
			relatorioConsulta.setNomePaciente(c.getPaciente().getUsuario().getNome());
			relatorioConsulta.setNomeSecretaria(c.getSecretaria().getUsuario().getNome());
			
			if (c.getTipo().equals(TipoConsulta.CONVENIO)) {
				relatorioConsulta.setConvenio(c.getConvenio().getNome());
			}
			
			if (c.getStatus().equals(StatusConsulta.ATRASADA) || 
				c.getStatus().equals(StatusConsulta.FINALIZADA) ||
				c.getStatus().equals(StatusConsulta.PAGA)) {
				valorLiquido += c.getValor();
			}
			
			valorBruto += c.getValor();
			
			relatorioConsulta.setQtAtrasada(qtAtrasada);
			relatorioConsulta.setQtCancelada(qtCancelada);
			relatorioConsulta.setQtFinalizada(qtFinalizada);
			relatorioConsulta.setQtMarcada(qtMarcada);
			relatorioConsulta.setQtPaga(qtPaga);
			relatorioConsulta.setQtPendente(qtPendente);
			relatorioConsulta.setQtRealizada(qtRealizada);
			
			relatorioConsulta.setQtTotal(qtTotal);
			
			relatorioConsulta.setStatus(c.getStatus().toString());
			relatorioConsulta.setValorConsulta(c.getValor());
			
			relatorioConsultas.add(relatorioConsulta);
		}
		
		for (RelatorioConsulta rc : relatorioConsultas) {
			rc.setValorBruto(valorBruto);
			rc.setValorLiquido(valorLiquido);
		}
		
		return relatorioConsultas;
	}
	
	@Override
	public List<RelatorioFaturamento> findRelatorioFaturamentosByFilters(RelatorioFaturamento relatorioFaturamento) 
			throws ParseException, DateParseException {
		
		List<RelatorioFaturamento> relatorioFaturamentos = new ArrayList<RelatorioFaturamento>();
		List<RelatorioFaturamento> relFaturamentos = new ArrayList<RelatorioFaturamento>();
		
		Double valorTotal = 0.0;
		
		List<StatusConsulta> statusList = new ArrayList<StatusConsulta>();
		statusList.add(StatusConsulta.ATRASADA);
		statusList.add(StatusConsulta.PAGA);
		statusList.add(StatusConsulta.FINALIZADA);
		
		List<Consulta> consultas = consultaRepository
				.consultasBetweenDatesAndStatus(relatorioFaturamento.getDataInicial(), relatorioFaturamento.getDataFinal(), statusList);
		
		if (null != consultas) { 
			for (Consulta c : consultas) {
				if(c.getDataPagamento() != null){
					RelatorioFaturamento rf = new RelatorioFaturamento();
					
					rf.setTipo(String.valueOf(TipoCaixa.ENTRADA));
					rf.setDescricao("CONSULTA [" + c.getStatus().toString() + "]");
					rf.setDataItem(DateUtils.convertDataUStoBR(c.getDataPagamento()));
					rf.setValorItem(c.getValor());
					
					valorTotal += c.getValor();
					
					relatorioFaturamentos.add(rf);
				}
			}
		}
		
		List<Debito> debitos = debitoRepository.findByPeriod(relatorioFaturamento.getDataInicial(), relatorioFaturamento.getDataFinal());
		
		if (null != debitos) {
			for (Debito d : debitos) {
				RelatorioFaturamento rf = new RelatorioFaturamento();
				
				rf.setTipo(String.valueOf(TipoCaixa.SAIDA));
				rf.setDescricao(d.getDescricao());
				rf.setDataItem(DateUtils.convertDataUStoBR(d.getDataCadastro()));
				rf.setValorItem(d.getValorTotal());
				
				valorTotal -= d.getValorTotal();
				
				relatorioFaturamentos.add(rf);
			}
		}
		
		List<Credito> creditos = creditoRepository.findByPeriod(relatorioFaturamento.getDataInicial(), relatorioFaturamento.getDataFinal());
		
		if (null != creditos) {
			for (Credito c : creditos) {
				RelatorioFaturamento rf = new RelatorioFaturamento();
				
				rf.setTipo(String.valueOf(TipoCaixa.ENTRADA));
				rf.setDescricao(c.getDescricao());
				rf.setDataItem(DateUtils.convertDataUStoBR(c.getDataCadastro()));
				rf.setValorItem(c.getValorTotal());
				
				valorTotal += c.getValorTotal();
				
				relatorioFaturamentos.add(rf);
			}
		}
		
		if (null != relatorioFaturamentos) {
			for (RelatorioFaturamento rf : relatorioFaturamentos) {
				rf.setDataInicial(DateUtils.convertDataUStoBR(relatorioFaturamento.getDataInicial()));
				rf.setDataFinal(DateUtils.convertDataUStoBR(relatorioFaturamento.getDataFinal()));
				rf.setValorTotal(valorTotal);
				
				relFaturamentos.add(rf);
			}
		}
		
		return relFaturamentos;
	}

}